package com.it00zyq.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.it00zyq.admin.param.ArticleParam;
import com.it00zyq.admin.result.ArticleResult;
import com.it00zyq.admin.result.BaseDataResult;
import com.it00zyq.admin.result.HotArticleResult;
import com.it00zyq.admin.service.ArticleService;
import com.it00zyq.admin.util.HotArticleUtil;
import com.it00zyq.admin.util.MDUtil;
import com.it00zyq.common.config.RedisConfig;
import com.it00zyq.common.entity.*;
import com.it00zyq.common.enums.ArticleEnum;
import com.it00zyq.common.enums.DeletedEnum;
import com.it00zyq.common.mapper.ArticleMapper;
import com.it00zyq.common.mapper.HtmlDataMapper;
import com.it00zyq.common.mapper.RawDataMapper;
import com.it00zyq.common.mapper.TypeMapper;
import com.it00zyq.common.param.ListParam;
import com.it00zyq.common.utils.ApiException;
import com.it00zyq.common.utils.JwtUtil;
import com.it00zyq.common.utils.PageVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author zyq
 * @Date 2022/4/29 13:15
 * @Description TODO
 * @Version 1.0
 **/
@Service
@Slf4j
@RequiredArgsConstructor
public class ArticleServiceImpl implements ArticleService {

    private final ArticleMapper articleMapper;
    private final RawDataMapper rawDataMapper;
    private final HtmlDataMapper htmlDataMapper;
    private final JwtUtil jwtUtil;
    private final HotArticleUtil articleUtil;
    private final TypeMapper typeMapper;
    private final RedisTemplate<String, Object> template;
    private static RedisTemplate<String, Object> redisTemplate;

    @PostConstruct
    public void init() {
        redisTemplate = template;
    }

    @Override
    @Transactional
    public void publish(ArticleParam param, String token) {
        Article article = new Article();
        User user = jwtUtil.getUser(token);
        Type type = typeMapper.selectById(param.getTypeId());
        BeanUtils.copyProperties(param, article);

        if (!ObjectUtils.isEmpty(type)) {
            article.setTypeName(type.getName());
        }

        article.setDeleted(DeletedEnum.NORMAL.getCode())
                .setPublishTime(ArticleEnum.PUBLISHED.getCode().equals(param.getState()) ? new Date() : null)
                .setUsername(user.getUsername())
                .setUserId(user.getId());

        // 文章摘要为空时，截取文章内容的前100个字符作为文章摘要
        if (!StringUtils.hasLength(param.getAbstraction())) {
            article.setAbstraction(MDUtil.delHtmlTags(param.getHtmlContent()));
        }
        articleMapper.insert(article);
        rawDataMapper.insert(new RawData().setArticleId(article.getId()).setRawContent(param.getRawContent()));
        htmlDataMapper.insert(new HtmlData().setArticleId(article.getId()).setHtmlContent(param.getHtmlContent()));

        // 更新Redis数据
        template.opsForHash().put(RedisConfig.VIEW_KEY,RedisConfig.VIEW_PRE_KEY + article.getId(), 0);
    }

    @Override
    public void modify(ArticleParam param) {
        Article article = articleMapper.selectById(param.getId());
        if (ObjectUtils.isEmpty(article)) {
            throw new ApiException("文章信息不存在");
        }
        Type type = typeMapper.selectById(param.getTypeId());

        article.setTitle(param.getTitle());
        article.setAbstraction(param.getAbstraction());
        article.setState(param.getState());
        article.setTypeId(param.getTypeId());
        article.setTypeName(type.getName());

        RawData rawData = rawDataMapper.selectById(article.getId());
        HtmlData htmlData = htmlDataMapper.selectById(article.getId());
        if (ObjectUtils.isEmpty(rawData) || ObjectUtils.isEmpty(htmlData)) {
            throw new ApiException("文章内容不存在");
        }
        rawData.setRawContent(param.getRawContent());
        htmlData.setHtmlContent(param.getHtmlContent());
        rawDataMapper.updateById(rawData);
        htmlDataMapper.updateById(htmlData);
        articleMapper.updateById(article);

    }

    @Override
    public ArticleResult detail(Integer id) {
        Article article = articleMapper.selectById(id);
        if (ObjectUtils.isEmpty(article)) {
            throw new ApiException("文章不存在");
        }
        ArticleResult result = new ArticleResult();
        BeanUtils.copyProperties(article, result);
        result.setRawContent(rawDataMapper.selectById(article.getId()).getRawContent());
        result.setHtmlContent(htmlDataMapper.selectById(article.getId()).getHtmlContent());
        result.setReadCount((Integer) redisTemplate.opsForHash().get(RedisConfig.VIEW_KEY, RedisConfig.VIEW_PRE_KEY + article.getId()));
        // 更新阅读量 当前文章阅读量和总阅读量
        template.opsForHash().increment(RedisConfig.VIEW_KEY,RedisConfig.VIEW_PRE_KEY + article.getId(), 1);
        articleUtil.insert(new HotArticleResult()
                .setId(article.getId())
                .setTitle(article.getTitle())
                .setReadCount((Integer) redisTemplate.opsForHash().get(RedisConfig.VIEW_KEY, RedisConfig.VIEW_PRE_KEY + article.getId())));
        template.opsForHash().increment(RedisConfig.VIEW_KEY,RedisConfig.VIEW_TOTAL_KEY, 1);
        return result;
    }

    @Override
    public PageVO list(ListParam param) {
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(param.getTypeId())) {
            wrapper.eq("type_id", param.getTypeId());
        }
        if (!ObjectUtils.isEmpty(param.getState())) {
            wrapper.eq("state", param.getState());
        }
        wrapper.eq("state", ArticleEnum.PUBLISHED.getCode());
        Page<Article> page = new Page<>(param.getPageNum(), param.getPageSize());
        IPage<Article> articleIPage = articleMapper.selectPage(page, wrapper);

        // 添加阅读量属性值
        List<ArticleResult> resultList = articleIPage.getRecords().stream().map(ArticleServiceImpl::convert).collect(Collectors.toList());
        return PageVO.convert(articleIPage, resultList);
    }

    @Override
    public BaseDataResult baseData() {
        Integer articleCount = articleMapper.selectCount(null);
        Integer readCount = (Integer) template.opsForHash().get(RedisConfig.VIEW_KEY,RedisConfig.VIEW_TOTAL_KEY);
        BaseDataResult result = new BaseDataResult();
        result.setArticleCount(articleCount);
        result.setReadCount(readCount);
        result.setArticles(articleUtil.getHotList());
        return result;
    }


    /**
     * 将Article转换为ArticleResult，添加阅读量属性
     */
    private static ArticleResult convert(Article article) {
        ArticleResult result = new ArticleResult();
        BeanUtils.copyProperties(article, result);
        result.setReadCount((Integer) redisTemplate.opsForHash().get(RedisConfig.VIEW_KEY, RedisConfig.VIEW_PRE_KEY + article.getId()));
        return result;
    }



}
